home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i090: Find security holes in shell-escapes
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: ihnp4!utzoo!hcr!hcrvx1!hugh
- Mod.sources: Volume 7, Issue 90
- Archive-name: forktest
-
- I would like to submit the following program to mod.sources. I hope
- that the comments are sufficient explanation. I don't see that a
- manual is worthwhile.
-
- I have run this program under System V and Version 7. I have not
- tested it under BSD, but I know of no impediment.
-
- With this program, I have found bugs in a number of UNIX System V
- utilities. I am sure that BSD programs would be just as buggy, but
- I haven't tested them. Here are some examples:
-
- Programs that leave extra file descriptors open:
- sdb ! command
- mailx ~! command during message composition, and ! command (two extra)
- mail ! command
- rn ! or | command (5 extra!)
- cu ~! command (one extra: number 5)
-
- Programs that leave signals ignored:
- mailx ~! command (SIGINT!)
- rn ! and | commands (SIGEMT!?)
-
- I think that this list shows that it is easy to get fork(2) wrong.
- I hope programmers will use ForkTest to catch this type of bug
- early. Exercise for the reader: what can you scribble on with those
- extra file descriptors?
-
- Hugh Redelmeier (416) 922-1937
- utzoo!hcr!hugh
-
- [ I wrote the Makefile and README. --r$ ]
- ----------CUT HERE----------
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If all goes well, you will see the message "End of shell archive."
- # Contents: Makefile README forktest.c
- # Wrapped by rs@mirror on Wed Dec 10 13:44:46 1986
- PATH=/bin:/usr/bin:/usr/ucb; export PATH
- echo shar: extracting "'Makefile'" '(52 characters)'
- if test -f 'Makefile' ; then
- echo shar: will not over-write existing file "'Makefile'"
- else
- sed 's/^X//' >Makefile <<'@//E*O*F Makefile//'
- X
- Xforktest: forktest.c
- X $(CC) $(CFLAGS) -o forktest
- X
- @//E*O*F Makefile//
- if test 52 -ne "`wc -c <'Makefile'`"; then
- echo shar: error transmitting "'Makefile'" '(should have been 52 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'README'" '(253 characters)'
- if test -f 'README' ; then
- echo shar: will not over-write existing file "'README'"
- else
- sed 's/^X//' >README <<'@//E*O*F README//'
- X
- X[ This program is designed to be called by programs that allow
- X shell escapes. It prints out the argc,argv parameters, and
- X lists the disposition of signals, alarm calls, etc. The fun
- X part is when it lists the open file descriptors... -r$ ]
- @//E*O*F README//
- if test 253 -ne "`wc -c <'README'`"; then
- echo shar: error transmitting "'README'" '(should have been 253 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'forktest.c'" '(3059 characters)'
- if test -f 'forktest.c' ; then
- echo shar: will not over-write existing file "'forktest.c'"
- else
- sed 's/^X//' >forktest.c <<'@//E*O*F forktest.c//'
- X/* Fork Test: display args, open files, signals, etc.
- X *
- X * Simple as this program is, it has found bugs in the
- X * way a number of programs fork off children. To test
- X * how a program is invoking its children, run this
- X * program as a child.
- X *
- X * Generally, processes should be created with:
- X *
- X * - a reasonable arg count & list
- X * - arg 0 should look like the name of the command
- X *
- X * - real and effective UIDs and GIDs should be reasonable.
- X * Beware setuid programs that fork children!
- X *
- X * - no pending alarm. Version 7 apparently does not
- X * reset alarms upon an exec!
- X *
- X * - file descriptors 0 (STDIN), 1 (STDOUT), and 2 (STDERR)
- X * opened reasonably
- X * - all other file descriptors closed (this program will
- X * describe all open channels)
- X *
- X * - all signals (except SIGKILL) set to SIG_DFL (this
- X * program will print all signals set otherwise)
- X *
- X * The output is fairly simple to understand. When in
- X * doubt, read the code (and a UNIX manual: exec(2),
- X * getuid(2), alarm(2), signal(2), stat(2)).
- X *
- X * Room for Improvement:
- X *
- X * - strings should be printed in a way that shows funny characters.
- X * - show misc. other bits of state
- X * - PID (who cares?)
- X * - umask
- X * - ulimit (System V)
- X * - stty settings of open TTYs
- X *
- X * Copyright (c) 1986 March 11 D. Hugh Redelmeier
- X *
- X * This program may be distributed and used without restriction.
- X */
- X
- X#include <stdio.h>
- X
- Xextern unsigned alarm(); /* should be unsigned, but may be int */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- Xstruct stat sb;
- X
- X#include <errno.h>
- Xextern int errno;
- Xextern char *sys_errlist[];
- X
- X#include <signal.h>
- X
- Xint (*signal())();
- X
- Xmain(argc, argv, envp)
- Xint argc;
- Xchar **argv, **envp;
- X{
- X register int i;
- X unsigned al = alarm(0); /* get it while it is hot */
- X
- X printf("%d arg(s):", argc);
- X for (i=0; i<argc; i++)
- X if (argv[i] == NULL)
- X printf(" NULL!");
- X else
- X printf(" \"%s\"", argv[i]);
- X printf("\n");
- X if (argv[argc] != NULL)
- X printf("Arg list is not ended with a NULL!\n");
- X
- X printf("Real UID = %d, GID = %d; Effective UID = %d, GID = %d.\n",
- X getuid(), getgid(), geteuid(), getegid());
- X
- X if (al)
- X printf("Alarm set to go off in %u seconds.\n", al);
- X
- X printf("File Descriptors:\n");
- X for (i=0; i!=40; i++) /* I hope 40 is enough. */
- X if (fstat(i, &sb) == -1) {
- X if (errno != EBADF)
- X printf("\t%d error: %s\n", i, sys_errlist[errno]);
- X } else {
- X printf("\t%d: dev=%d, ino=%d, perm=0%04o, ",
- X i, sb.st_dev, sb.st_ino, sb.st_mode&07777);
- X switch (sb.st_mode & S_IFMT) {
- X case S_IFREG:
- X printf("pipe or regular file\n");
- X break;
- X /* extend as desired */
- X default:
- X printf("IFMT=0%o\n", sb.st_mode>>12);
- X break;
- X }
- X }
- X
- X printf("Signals:\n");
- X for (i=1; i!=40; i++) { /* I hope 40 is enough. */
- X register int n = (int) signal(i, SIG_IGN);
- X switch (n) {
- X case -1:
- X case SIG_DFL:
- X break;
- X case SIG_IGN:
- X printf("\t%d: SIG_IGN\n", i);
- X break;
- X default:
- X printf("\t%d: %d\n", i, n);
- X break;
- X }
- X }
- X
- X printf("Environment:\n");
- X for (i=0; envp[i]!=NULL; i++)
- X printf("\t\"%s\"\n", envp[i]);
- X
- X exit(0);
- X}
- @//E*O*F forktest.c//
- if test 3059 -ne "`wc -c <'forktest.c'`"; then
- echo shar: error transmitting "'forktest.c'" '(should have been 3059 characters)'
- fi
- fi # end of overwriting check
- echo shar: "End of shell archive."
- exit 0
-